package com.itheima.d1_stream;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;

//目标：掌握Stream流常见中间方法的使用
public class Demo3 {
    public static void main(String[] args) {
        List<Double> scores = new ArrayList<>();
        Collections.addAll(scores, 88.5, 100.0, 60.0, 99.0, 9.5, 99.6, 25.0);

        // 需求1：找出成绩大于等于60分的数据，并升序后，再输出。
        //1.1 获取流
        Stream<Double> scoresStream = scores.stream();
        //1.2 筛选出符合条件的成绩，Stream的筛选方法是filter
        /*
        scoresStream.filter(new Predicate<Double>() {
            @Override
            public boolean test(Double data) {
                //方法形参就是流中的每一个数据，当方法返回true的时候，这个数据会被保留到新的Stream流中，否则就丢弃！
                //需求：筛选出大于等于60分的数据
                return data >= 60;
            }
        });
        */
        Stream<Double> newScoresStream = scoresStream.filter(data -> data >= 60);
        newScoresStream.forEach(System.out::println);
        //尝试用旧的Stream流对象调用遍历功能
        //scoresStream.forEach(System.out::println);
        //说明：Stream流一旦调用中间方法，这个流会被关闭，再也无法使用，只能使用得到的新的流！
        System.out.println("----------------------");

        List<Student> stus = new ArrayList<>();
        Student s1 = new Student("蜘蛛精", 26, 172.5);
        Student s2 = new Student("蜘蛛精", 26, 172.5);
        Student s3 = new Student("紫霞", 23, 167.6);
        Student s4 = new Student("白晶晶", 25, 169.0);
        Student s5 = new Student("牛魔王", 35, 183.3);
        Student s6 = new Student("牛夫人", 34, 168.5);
        Collections.addAll(stus, s1, s2, s3, s4, s5, s6);

        // 需求2：找出年龄大于等于23,且年龄小于等于30岁的学生，并按照年龄降序输出.
        //2.1 获取流
        stus.stream()
                //2.2 筛选数据，使用中间方法：filter
                .filter(student -> student.getAge() >= 23 && student.getAge() <= 30)
                //2.3 按照年龄降序排序，使用中间方法：sorted
                .sorted((o1, o2) -> o2.getAge() - o1.getAge())
                //2.4 遍历输出，使用终结方法：forEach
                .forEach(System.out::println);
        System.out.println("----------------------");

        // 需求3：取出身高最高的前3名学生，并输出。
        //3.1 获取流
        stus.stream()
                //3.2 按照身高升序排序，用中间方法：sorted
                .sorted((o1, o2) -> Double.compare(o1.getHeight(), o2.getHeight()))
                //3.3 升序后，身高最高的3名学生在最后，需要跳过（集合长度 - 3）个，跳过用中间方法：skip
                .skip(stus.size() - 3)
                //3.4 遍历打印
                .forEach(System.out::println);
        System.out.println("----------------------");

        // 需求4：取出身高倒数的2名学生，并输出
        //4.1 获取流
        stus.stream()
                // 4.2 对流中数据按身高升序
                .sorted((o1, o2) -> Double.compare(o1.getHeight(), o2.getHeight()))
                // 4.3 排序后，身高倒数的在前两个，获取流中前几个数据，用中间方法：limit
                .limit(2)
                // 4.4 遍历打印
                .forEach(System.out::println);
        System.out.println("----------------------");

        // 需求5：找出身高超过168的学生、去除重复的学生（属性值相同，则认为元素重复）、获取所有学生的姓名、并输出
        // 5.1 获取流
        stus.stream()
                // 5.2 筛选身高超过168的学生
                .filter(stu -> stu.getHeight() > 168)
                // 5.3 去除重复的学生（属性相同就要去除），使用中间方法：distinct
                // distinct方法底层是根据hashCode和equals方法去除重复
                .distinct()
                // 5.4 从原来的流中提取学生姓名到新的流中，使用中间方法：map
                /*
                .map(new Function<Student, String>() {
                    @Override
                    public String apply(Student student) {
                        //形式参数是原来流中的数据，返回值是需要返回到新的流中的数据
                        //需求：从学生对象中提取姓名数据返回到新的流中
                        return student.getName();
                    }
                })
                */
                .map(Student::getName)
                // 5.5 遍历输出
                .forEach(System.out::println);
        System.out.println("----------------------");

        String[] arr1 = {"a", "b"};
        String[] arr2 = {"c", "d"};
        //需求6：将arr1和arr2的数据合并在一起，并打印
        // 6.1 分别获取两个数组的Stream
        Stream<String> stream1 = Arrays.stream(arr1);
        Stream<String> stream2 = Arrays.stream(arr2);

        //6.2 Stream接口提供了静态方法 concat，可以合并
        Stream.concat(stream1, stream2)
                // 6.3 遍历打印
                .forEach(System.out::println);

    }
}
